// The MIT License

// Copyright (c) 2009 Massachusetts Institute of Technology

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import Connectable::*;
import GetPut::*;
import ClientServer::*;
import RegFile::*;
import FIFO::*;
import FIFOF::*;
import RWire::*;

//AWB includes
`include "awb/provides/low_level_platform_interface.bsh"
`include "awb/provides/soft_connections.bsh"
`include "awb/provides/common_services.bsh"

// Local includes
`include "awb/provides/processor_library.bsh"
//`include "asim/rrr/remote_server_stub_PROCESSORSYSTEMRRR.bsh"
`include "awb/provides/common_services.bsh"
//`include "awb/dict/STATS_PROCESSOR.bsh"

interface Proc;

  // Interface from processor to caches
  interface Client#(DataReq,DataResp) dmem_client;
  interface Client#(InstReq,InstResp) imem_client;

  // Interface for enabling/disabling statistics on the rest of the core
//  interface Get#(Bool) statsEn_get;

	// wjun
	interface Get#(RunRes) run_result;
//	interface Put#(RunRes) feed_compressed;
	interface Put#(StepRes) state_feed;

	method Bit#(32) procdata_get;

endinterface

typedef enum { Init, PCgen, Exec, Writeback, PCwrite } Stage deriving(Eq,Bits);

//-----------------------------------------------------------
// Register file module
//-----------------------------------------------------------

interface RFile;
   method Action   wr( Rindx rindx, Bit#(32) data );
   method Bit#(32) rd1( Rindx rindx );
   method Bit#(32) rd2( Rindx rindx );
endinterface

module mkRFile( RFile );
   
   RegFile#(Rindx,Bit#(32)) rfile <- mkRegFileFull();
   
   method Action wr( Rindx rindx, Bit#(32) data );
      rfile.upd( rindx, data );
   endmethod
   
   method Bit#(32) rd1( Rindx rindx );
      return ( rindx == 0 ) ? 0 : rfile.sub(rindx);
   endmethod
   
   method Bit#(32) rd2( Rindx rindx );
      return ( rindx == 0 ) ? 0 : rfile.sub(rindx);
   endmethod

endmodule

//-----------------------------------------------------------
// Helper functions
//-----------------------------------------------------------

function Bit#(32) slt( Bit#(32) val1, Bit#(32) val2 );
   return zeroExtend( pack( signedLT(val1,val2) ) );
endfunction

function Bit#(32) sltu( Bit#(32) val1, Bit#(32) val2 );
   return zeroExtend( pack( val1 < val2 ) );
endfunction

function Bit#(32) rshft( Bit#(32) val );
   return zeroExtend(val[4:0]);
endfunction

//-----------------------------------------------------------
// Reference processor
//-----------------------------------------------------------

module  [CONNECTED_MODULE] mkProc( Proc );

   //-----------------------------------------------------------
   // Debug port
   
//   ServerStub_PROCESSORSYSTEMRRR server_stub <- mkServerStub_PROCESSORSYSTEMRRR();   

   //-----------------------------------------------------------
   // State

	 // wjun
	 Reg#(Bit#(32)) exec_cycles <- mkReg(32'h0);
//	 FIFO#(Bit#(32)) cycleReqQ <- mkFIFO();
	 //FIFO#(RunRes) feedQ <- mkFIFO();
	 FIFO#(StepRes) statefeedQ <- mkSizedFIFO(16);
	 FIFOF#(RunRes) runResQ <- mkFIFOF();
	 Reg#(Bit#(AddrSz)) swAddr <- mkReg(0);

   // Standard processor state
   
	 // wjun
	 Reg#(Addr)  branchdelay    <- mkReg(32'h00000000);
   
   Reg#(Addr)  pc    <- mkReg(32'h004001d0);
   Reg#(Stage) stage <- mkReg(Init);
   RFile       rf    <- mkRFile;

   // Coprocessor state - connected by way of RRR
   
   Reg#(Bit#(32)) cp0_tohost   <- mkReg(0);
  
   Reg#(Bit#(32)) cp0_fromhost <- mkReg(0);
  
//   Reg#(Bool)    cp0_statsEn  <- mkReg(False);
	 Reg#(Bit#(32)) procData <- mkReg(0);
  
   // Memory request/response state
   
   FIFO#(InstReq)  instReqQ    <- mkBFIFO1();
   FIFO#(InstResp) instRespQ   <- mkFIFO();

   FIFO#(DataReq)  dataReqQ    <- mkBFIFO1();
   FIFO#(DataResp) dataRespQ   <- mkFIFO();

   // Statistics state
//   STAT num_cycles <- mkStatCounter(`STATS_PROCESSOR_CYCLE_COUNT);
//   STAT num_inst <- mkStatCounter(`STATS_PROCESSOR_INST_COUNT);
	    // Statistics state                                                                                                                                                                    
//	 STAT num_cycles <- mkStatCounter(statName("PROCESSOR_CYCLE_COUNT", "PROCESSOR: Cycle count: "));
//	 STAT num_inst <- mkStatCounter(statName("PROCESSOR_INST_COUNT", "PROCESSOR: Instruction count: "));

   //-----------------------------------------------------------
   // Rules

   let pc_plus4 = pc + 4;

	 // wjun
	 Reg#(Bool) waiting <- mkReg(True);

	 /*
	 //rule cyclereq;
	 rule cyclereq ( exec_cycles == 0 );
	 	exec_cycles <= exec_cycles + cycleReqQ.first();
		cycleReqQ.deq();
	 endrule
	 */

	 rule feed_compr(waiting);
	 	//feedQ.deq();
		//let f = feedQ.first();
	 	statefeedQ.deq();
		let c = statefeedQ.first();
		if (c.longMatch)
		begin
			exec_cycles <= exec_cycles + {3'h0, c.longCount};
			waiting <= False;
		end 
		else if (c.matchcount > 0 )
		begin
			exec_cycles <= exec_cycles + {16'h0,c.matchcount};
			waiting <= False;
			$display( "starting prediction %d\n", c.matchcount );
		end
		else
		begin
			if (c.pc > 0)
			begin
				pc <= c.pc;
				branchdelay <= 0;
				$display ( "PC<%x", c.pc );
			end

			if ( c.regChange )
				rf.wr(c.target, c.value);
			if (c.memAcc == memAccRead)
	    	dataReqQ.enq( StoreReq{ tag:0, addr:c.addr, data:c.value } );
			else if (c.memAcc == memAccWrite)
	    	dataReqQ.enq( StoreReq{ tag:0, addr:c.addr, data:c.value } );
		end
	 endrule


	Reg#(Bit#(32)) cycles_count <- mkReg(0);
	Reg#(Bit#(32)) cycle_start <- mkReg(0);
	rule inc_cycle;
		cycles_count <= cycles_count + 1;
	endrule

	Reg#(Bit#(5)) init_idx <- mkReg(31);
	rule init ( stage == Init && !waiting );
		if ( init_idx == 0 ) stage <= PCgen;
		init_idx <= init_idx - 1;
		rf.wr(init_idx, 0);
	endrule


	FIFO#(StepRes) srExec_wb <- mkFIFO();
	FIFO#(StepRes) srResQ <- mkFIFO();
	Reg#(Bit#(8)) epoch <- mkReg(0);

   rule pcgen ( stage == PCgen && !waiting);
	 		cycle_start <= cycles_count;

      //traceTiny("mkProc", "pc",pc);
      //traceTiny("mkProc", "pcgen","P");

			// wjun
			if ( exec_cycles > 0 ) 
			begin
      	instReqQ.enq( LoadReq{ addr:pc, tag:0, size:0 } );
				exec_cycles <= exec_cycles - 1;
      	stage   <= Exec;
				$display ( "PC>%x", pc );
			end
			else /*if ( !waiting )*/
			begin
				//TODO FIXME <- when pipelined, this needs to go to last step
				runResQ.enq(RunRes{traceType:doneVal, size:0, target:0, value1:0, value2:0});

				waiting <= True;
			end

   endrule

   rule exec ( stage == Exec && !waiting );
      // Some abbreviations
      let sext = signExtend;
      let zext = zeroExtend;
      let sra  = signedShiftRight;
      
      // Get the instruction
      
      instRespQ.deq();
			let epoch_tag = 0;
      Instr inst 
      = case ( instRespQ.first() ) matches
	   		tagged LoadResp  .ld : 
				begin
					//epoch_tag <= ld.tag;
					return unpack(ld.data);
				end
	   		tagged StoreResp .st : return ?;
			endcase;

//			if ( epoch == epoch_tag )
			if ( True )
			begin

				Stage next_stage = PCwrite;
				Addr  next_pc    = pc_plus4;
				// Tracing
				Maybe#(RunRes) resval = tagged Invalid;

				case ( inst ) matches

		 // -- Memory Ops ------------------------------------------------      
		 //TODO: memops except lw and sw are not correctly implemented
		 // (in datacacheblocking.bsv and such)
		 tagged LW .it : 
				begin
					Addr addr = rf.rd1(it.rbase) + sext(it.offset);
					dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst), size:4 } );
					next_stage = Writeback;
					// wjun - No value yet, so work on it later
					swAddr <= addr;
				end

		 tagged SW .it : 
				begin
					Addr addr = rf.rd1(it.rbase) + sext(it.offset);
					dataReqQ.enq( StoreReq{ tag:4, addr:addr, data:rf.rd1(it.rsrc) } );
					// wjun
					resval = tagged Valid RunRes {traceType:memWriteVal, size:4, target:it.rsrc, value1:addr, value2:rf.rd1(it.rsrc)};
				end
			tagged LB .it :
				begin
					Addr addr = rf.rd1(it.rbase) + sext(it.offset);
					dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst), size:1 } );
					next_stage = Writeback;
					swAddr <= addr;
				end
			tagged LH .it :
				begin
					Addr addr = rf.rd1(it.rbase) + sext(it.offset);
					dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst) , size:2 } );
					next_stage = Writeback;
					swAddr <= addr;
				end
			tagged LBU .it :
				begin
					Addr addr = rf.rd1(it.rbase) + sext(it.offset);
					dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst) , size:1 } );
					next_stage = Writeback;
					swAddr <= addr;
				end
			tagged LHU .it :
				begin
					Addr addr = rf.rd1(it.rbase) + sext(it.offset);
					dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst), size:2 } );
					next_stage = Writeback;
					swAddr <= addr;
				end
		 tagged SB .it : 
				begin
					Addr addr = rf.rd1(it.rbase) + sext(it.offset);
					dataReqQ.enq( StoreReq{ tag:1, addr:addr, data:rf.rd1(it.rsrc) } );
					// wjun
					resval = tagged Valid RunRes {traceType:memWriteVal, size:1, target:it.rsrc, value1:addr, value2:rf.rd1(it.rsrc)};
				end
		 tagged SH .it : 
				begin
					Addr addr = rf.rd1(it.rbase) + sext(it.offset);
					dataReqQ.enq( StoreReq{ tag:2, addr:addr, data:rf.rd1(it.rsrc) } );
					// wjun
					resval = tagged Valid RunRes {traceType:memWriteVal, size:2, target:it.rsrc, value1:addr, value2:rf.rd1(it.rsrc)};
				end

		 // -- Simple Ops ------------------------------------------------      

		 tagged ADDIU .it : 
				begin
					rf.wr( it.rdst, rf.rd1(it.rsrc) + sext(it.imm) );
					// wjun
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc)+sext(it.imm), value2:0};
				end
		 tagged SLTI  .it : 
				begin
					rf.wr( it.rdst, slt( rf.rd1(it.rsrc), sext(it.imm) ) );
					// wjun
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:slt(rf.rd1(it.rsrc),sext(it.imm)), value2:0};
				end
		 tagged SLTIU .it : 
				begin
					rf.wr( it.rdst, sltu( rf.rd1(it.rsrc), sext(it.imm) ) );
					// wjun
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:sltu(rf.rd1(it.rsrc),sext(it.imm)), value2:0};
				end
		 tagged ANDI  .it : 
				begin
					 Bit#(32) zext_it_imm = zext(it.imm);
					 rf.wr( it.rdst, rf.rd1(it.rsrc) & zext_it_imm );
					// wjun
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc) & zext_it_imm, value2:0};
				end
		 tagged ORI   .it : 
				begin
					 Bit#(32) zext_it_imm = zext(it.imm);
					 rf.wr( it.rdst, rf.rd1(it.rsrc) | zext_it_imm );
					// wjun
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc) | zext_it_imm, value2:0};
				end
		 tagged XORI  .it : 
				begin
					 Bit#(32) zext_it_imm = zext(it.imm);
					 rf.wr( it.rdst, rf.rd1(it.rsrc) ^ zext_it_imm );
					// wjun
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc) ^ zext_it_imm, value2:0};
				end
		 tagged LUI   .it : 
				begin
					 Bit#(32) zext_it_imm = zext(it.imm);
					 rf.wr( it.rdst, (zext_it_imm << 32'd16) );
					// wjun
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:zext_it_imm << 32'd16, value2:0};
				end
		 
		 tagged SLL   .it : 
				begin
					 Bit#(32) zext_it_shamt = zext(it.shamt);
					 rf.wr( it.rdst, rf.rd1(it.rsrc) << zext_it_shamt );
					// wjun
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc) << zext_it_shamt, value2:0};
				end
		 tagged SRL   .it : 
				begin
					 Bit#(32) zext_it_shamt = zext(it.shamt);
					 rf.wr( it.rdst, rf.rd1(it.rsrc) >> zext_it_shamt );
					// wjun
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc) >> zext_it_shamt, value2:0};
				end
		 tagged SRA   .it : 
				begin
					 Bit#(32) zext_it_shamt = zext(it.shamt);
					 rf.wr( it.rdst, sra( rf.rd1(it.rsrc), zext_it_shamt ));
					// wjun
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:sra(rf.rd1(it.rsrc), zext_it_shamt), value2:0};
				end
		 tagged SLLV  .it : 
			begin
				rf.wr( it.rdst, rf.rd1(it.rsrc) << rshft(rf.rd2(it.rshamt)) );
				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc) << rshft(rf.rd2(it.rshamt)), value2:0};
			end
		 tagged SRLV  .it :
			begin
				rf.wr( it.rdst, rf.rd1(it.rsrc) >> rshft(rf.rd2(it.rshamt)) );

				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc) >> rshft(rf.rd2(it.rshamt)), value2:0};
			end
		 tagged SRAV  .it :
			begin
				rf.wr( it.rdst, sra( rf.rd1(it.rsrc), rshft(rf.rd2(it.rshamt)) ) );

				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:sra(rf.rd1(it.rsrc), rshft(rf.rd2(it.rshamt))), value2:0};
			end
		 tagged ADDU  .it : 
			begin
				Bit#(32) writeval = rf.rd1(it.rsrc1) + rf.rd2(it.rsrc2);
	//			rf.wr( it.rdst, rf.rd1(it.rsrc1) + rf.rd2(it.rsrc2) );
				rf.wr( it.rdst, writeval );
				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:writeval, value2:0};
			end
		 tagged SUBU  .it :
			begin
				rf.wr( it.rdst, rf.rd1(it.rsrc1) - rf.rd2(it.rsrc2) );
				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc1) - rf.rd2(it.rsrc2), value2:0};
			end
		 tagged AND   .it : 
			begin
				rf.wr( it.rdst, rf.rd1(it.rsrc1) & rf.rd2(it.rsrc2) );
				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc1) & rf.rd2(it.rsrc2), value2:0};
			end
		 tagged OR    .it : 
			begin
				rf.wr( it.rdst, rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2) );
				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2), value2:0};
			end
		 tagged XOR   .it : 
			begin
				rf.wr( it.rdst, rf.rd1(it.rsrc1) ^ rf.rd2(it.rsrc2) );
				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:rf.rd1(it.rsrc1) ^ rf.rd2(it.rsrc2), value2:0};
			end
		 tagged NOR   .it : 
			begin
				rf.wr( it.rdst, ~(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2)) );
				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:~(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2)), value2:0};
			end
		 tagged SLT   .it : 
			begin
				rf.wr( it.rdst, slt( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) );
				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:slt(rf.rd1(it.rsrc1), rf.rd2(it.rsrc2)), value2:0};
			end
		 tagged SLTU  .it :
			begin
				rf.wr( it.rdst, sltu( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) );
				// wjun
				resval = tagged Valid RunRes{traceType:regVal, size:0, target:it.rdst, value1:sltu(rf.rd1(it.rsrc1), rf.rd2(it.rsrc2)), value2:0};
			end

		 // -- Branches --------------------------------------------------

		 tagged BLEZ  .it : 
							if ( signedLE( rf.rd1(it.rsrc), 0 ) )
								 next_pc = pc_plus4 + (sext(it.offset) << 2);

		 tagged BGTZ  .it : 
							if ( signedGT( rf.rd1(it.rsrc), 0 ) ) 
								 next_pc = pc_plus4 + (sext(it.offset) << 2);

		 tagged BLTZ  .it : 
							if ( signedLT( rf.rd1(it.rsrc), 0 ) )
								 next_pc = pc_plus4 + (sext(it.offset) << 2);

		 tagged BGEZ  .it : 
							if ( signedGE( rf.rd1(it.rsrc), 0 ) )
								 next_pc = pc_plus4 + (sext(it.offset) << 2);

				tagged BEQ   .it : 
					if ( rf.rd1(it.rsrc1) == rf.rd2(it.rsrc2) )
						next_pc = pc_plus4 + (sext(it.offset) << 2);

				tagged BNE   .it : 
					if ( rf.rd1(it.rsrc1) != rf.rd2(it.rsrc2) )
						next_pc = pc_plus4 + (sext(it.offset) << 2);
				
				// -- Jumps -----------------------------------------------------
				
				tagged J     .it : 
					next_pc = { pc_plus4[31:28], it.target, 2'b0 };
				
				tagged JR    .it : 
					next_pc = rf.rd1(it.rsrc);

				tagged JAL   .it : 
				 begin
					rf.wr( 31, pc_plus4 );
					resval = tagged Valid RunRes{traceType:regVal, size:0, target:31, value1:pc_plus4, value2:0};
					next_pc = { pc_plus4[31:28], it.target, 2'b0 };
				 end

				tagged JALR  .it : 
				 begin
					rf.wr( it.rdst, pc_plus4 );
					next_pc = rf.rd1(it.rsrc);
				 end
				default : 
					$display( " RTL-ERROR : %m : Illegal instruction %x !", pc );

			endcase

			stage    <= next_stage;
	//		if ( next_stage == Writeback )
	//			$display ("next-writeback");

			if ( branchdelay > 0 )
			begin
				pc       <= branchdelay;
				branchdelay <= 0;
			end
			else
			begin
				if ( next_pc != pc_plus4)
					branchdelay <= next_pc;
				pc			<= pc_plus4;
			end

			if ( resval matches tagged Valid .d)
				runResQ.enq(d);

		end

//    if ( cp0_statsEn )
//     num_inst.incr();

  endrule

  rule writeback ( stage == Writeback && !waiting );
//	 	$display ("writeback!" );
    //traceTiny("mkProc", "writeback","W");
    dataRespQ.deq();

    case ( dataRespQ.first() ) matches
      tagged LoadResp .ld  : 
				begin
					rf.wr( truncate(ld.tag), ld.data );	
						
					// wjun
					runResQ.enq(RunRes{traceType:memReadVal, size:4, target:truncate(ld.tag), value1:swAddr, value2:ld.data});
				end
      tagged StoreResp .st : noAction;
    endcase

//    stage <= PCgen;
			// wjun
	    stage <= PCwrite;
  endrule

	rule pcwrite( stage == PCwrite && runResQ.notFull && !waiting );
//	 	$display ("pcwrite!" );
		// wjun
		runResQ.enq(RunRes{traceType:pcVal, size:0, target:0, value1:pc, value2:0});
		stage <= PCgen;

		$display ( "cycles taken: %x", cycles_count - cycle_start );
		procData <= cycles_count - cycle_start;
	endrule
/*
  rule inc_num_cycles;
    if ( cp0_statsEn )
      num_cycles.incr();
  endrule
*/
/*
  (* conservative_implicit_conditions *)
  rule handleCPUToHost;
    let req <- server_stub.acceptRequest_ReadCPUToHost();
    case (req)
      0: server_stub.sendResponse_ReadCPUToHost(cp0_tohost);
      1: server_stub.sendResponse_ReadCPUToHost(pc);
      2: server_stub.sendResponse_ReadCPUToHost(zeroExtend(pack(stage)));
    endcase
  endrule
*/


  //-----------------------------------------------------------
  // Methods

  interface Client imem_client;
    interface Get request  = fifoToGet(instReqQ);
    interface Put response = fifoToPut(instRespQ);
  endinterface

  interface Client dmem_client;
    interface Get request  = fifoToGet(dataReqQ);
    interface Put response = fifoToPut(dataRespQ);
  endinterface

//  interface Get statsEn_get      = regToGet(cp0_statsEn);
	method Bit#(32) procdata_get();
		return procData;
	endmethod

	// wjun
	//interface Put feed_compressed	= fifoToPut(feedQ);
	interface Put state_feed	= fifoToPut(statefeedQ);
	interface Get run_result	= fifofToGet(runResQ);

endmodule

